package cn.tnar.yunpark.huasai.nbiot;

import cn.tnar.yunpark.huasai.CRC16;
import cn.tnar.yunpark.util.DateTimeUtil;
import cn.tnar.yunpark.util.Util;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.ByteOrder;

/**
 * Created by tieh on 2017/6/22.
 */
public abstract class HuasaiNbiotMessage {

    private static final Logger log = LoggerFactory.getLogger(HuasaiNbiotMessage.class);

    /**
     * 包类型 0x20 - 车位状态变化事件， 0x21 - 心跳
     * offset: 0, length: 1
     */
    protected byte type;

    /**
     * 地磁编码
     * offset: 1, length: 10
     */
    protected byte[] magCode;

    /**
     * 批次号
     * length: 2
     */
    protected short packCount;

    /**
     * 地磁编号
     * offset: 26, length: 4
     */
    protected int magId;

    /**
     * 时间戳，单位为秒数
     * offset: 11, length: 8
     */
    protected long timestamp;

    protected int crc;

    protected ByteBuf buf;

    public String getSensorId() {
        return Integer.toString(magId);
    }

    public String getTime() {
        return DateTimeUtil.format(timestamp);
    }

    public abstract int getStatus();
    public abstract int getPower();
    public abstract int getRssi();

    protected abstract int getCrcOffset();

    protected void checkValid(byte[] data, int len) throws HuasaiException {
        if (len < 19) {
            String error = "报文长度太短，至少应该有19字节头部: " + len;
            log.warn(error);
            throw new HuasaiException(error);
        }
    }

    protected void parse(byte[] data, int len) throws HuasaiException {
        buf = Unpooled.wrappedBuffer(data, 0, len);
        buf.order(ByteOrder.BIG_ENDIAN);
        type = buf.getByte(0);
//        magCode = new byte[10];
//        buf.getBytes(1, magCode);
//        timestamp = buf.getLong(11);
//        if(timestamp < 30 * 24 * 3600) {
            // 如果地磁时间戳太小，使用本系统时间
        timestamp = System.currentTimeMillis() / 1000;
//        }
        crc = buf.getUnsignedShort(getCrcOffset());
    }

    private void checkChecksum(byte[] data, int len) throws HuasaiException {
        int calcCrc = CRC16.calc(data, 0, len - 2);
        if (crc != calcCrc) {
            String error = String.format("CRC校验错误: rcv=%04x,calc=%04x", crc, calcCrc);
            log.warn(error);
            throw new HuasaiException(error);
        }
    }

    public static HuasaiNbiotMessage decode(byte[] data, int len) throws HuasaiException {
        byte type = data[0];
        HuasaiNbiotMessage msg;
        switch (type) {
            case 0x20:
                msg = new HuasaiNbiotTrafficMessage();
                break;
            case 0x21:
                msg = new HuasaiNbiotKeepAliveMessage();
                break;
            default:
                throw new HuasaiException(String.format("未知消息类型: 0x%02X", type));
        }
        msg.checkValid(data, len);
        msg.parse(data, len);
        msg.checkChecksum(data, len);
        return msg;
    }
}
